using System.Windows;

namespace WPFTemplateLib.Attached
{
	/// <summary>
	/// [附加属性] 控制WPF应用程序是否能被自动化技术检测
	/// <para/>来自：https://github.com/Super0Lan/AutomationAssists（NuGet包：AutomationAssists）
	/// <para/>使用介绍：https://blog.csdn.net/qq_29198233/article/details/121098967
	/// </summary>
	public class AutomationAssists
	{
		public static bool GetCanAutomationed(DependencyObject obj)
		{
			return (bool)obj.GetValue(CanAutomationedProperty);
		}

		/// <summary>
		/// 设置 是否允许UI自动化
		/// </summary>
		public static void SetCanAutomationed(DependencyObject obj, bool value)
		{
			obj.SetValue(CanAutomationedProperty, value);
		}

		// Using a DependencyProperty as the backing store for CanAutomationed.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty CanAutomationedProperty =
			DependencyProperty.RegisterAttached("CanAutomationed", typeof(bool), typeof(AutomationAssists),
				new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits, OnCanAutomationedChanged));

		public static void OnCanAutomationedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			if(d is UIElement element)
			{
				if((bool)e.NewValue)
				{
					var hasAutomationPeer = typeof(UIElement).GetProperty("HasAutomationPeer",
						System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
					if(hasAutomationPeer != null)
					{
						hasAutomationPeer.SetValue(element, false);
					}

					var methond = typeof(UIElement).GetMethod("CreateAutomationPeer",
						System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
					if(methond != null)
					{
						var peer = methond.Invoke(element, null);
					}
				}
				else
				{
					var hasAutomationPeer = typeof(UIElement).GetProperty("HasAutomationPeer",
						System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
					if(hasAutomationPeer != null)
					{
						hasAutomationPeer.SetValue(element, true);
					}

					var field = typeof(UIElement).GetField("AutomationPeerField",
						System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
					if(field != null)
					{
						var automationPeerFieldValue = field.GetValue(element);
						if(automationPeerFieldValue != null)
						{
							var gMethod = automationPeerFieldValue.GetType().GetMethod("ClearValue");
							if(gMethod != null)
							{
								gMethod.Invoke(automationPeerFieldValue, new object[] { element });
							}
						}
					}
				}
			}
		}
	}
}
